<template>
  <div class="page-container">
    <!-- 顶部操作栏 -->
    <div class="top-bar flex " style="background: #212124;justify-content: space-between">
      <div style="color: #FFFFFF; line-height: 40px">
        当前您进入的是数学视频教学
      </div>
      <div class="icon-item flex" @click="fullScreenHandler"
           style="color: #FFFFFF; line-height: 40px; align-items: center">
        <template v-if="!isFull">
          <div class="i-mdi-fullscreen icon" style="margin-right: 10px;font-size: 30px"></div>
          <div class="text">全屏</div>
        </template>
        <template v-else>
          <div class="i-mdi-fullscreen-exit icon" style="margin-right: 10px;font-size: 30px"></div>
          <div class="text">退出全屏</div>
        </template>
      </div>
    </div>

    <!-- 视频区域 -->
    <div class="page-content">
      <!-- 主视频 -->
      <div class="stream-main flex justify-center items-center flex-col" id="stream_main" style="background: black">
        <img src="assets/vector.png" width="100" style="margin-bottom: 20px" alt="">
        <div style="color: #FFFFFF">主播正在拼命赶来噢</div>
      </div>

      <!-- 成员列表 -->
      <div class="stream-list" style="background: #212124;opacity: 0.82;">
        <div class="action-p">
          会议人员
        </div>
        <div class="stream-item" :key="i" v-for="(stream, i) in remoteStreamsList">
          <div class="text-white bg-black text-center">
            {{ stream.getUserId() }}
          </div>
          <div :id="stream.getId()"></div>
        </div>
      </div>
    </div>
    <!-- 底部操作栏 -->
    <div class="bottom-bar" style="background: #212124;">
      <div class="left">
        <div class="icon-item" @click="microphoneHandler">
          <div v-if="microStatus" class="i-mdi-microphone icon"></div>
          <div v-else class="i-mdi-microphone-off icon"></div>
          <div class="text">麦克风</div>
        </div>
        <div class="icon-item" @click="cameraHandler">
          <div v-if="cameraStatus" class="i-mdi-camera icon"></div>
          <div v-else class="i-mdi-camera-off icon"></div>
          <div class="text">摄像头</div>
        </div>
      </div>
      <div class="right">
        <div class="button"
             style="width: 253px;height: 56px;background: linear-gradient(92.93deg, #85D3FF 0.56%, #5350FA 98.29%);border-radius: 4px;"
             @click="handleLeave">结束会议
        </div>
      </div>

      <div class="center">
        <div class="icon-item" @click="shareScreenHandler">
          <template v-if="!shareScreenStatus">
            <div class="i-mdi-monitor-share icon"></div>
            <div class="text">共享屏幕</div>
          </template>
          <template v-else>
            <div class="i-mdi-projector-screen-variant-off-outline icon"></div>
            <div class="text">退出共享</div>
          </template>
        </div>

        <div class="icon-item" @click="inviteShow">
          <div class="i-mdi-account-plus icon"></div>
          <div class="text">邀请成员</div>
        </div>
        <!-- <div class="icon-item">
          <div class="i-mdi-dots-horizontal-circle icon"></div>
          <div class="text">更多</div>
        </div>
        <div class="icon-item">
          <div class="i-mdi-cog icon"></div>
          <div class="text">设置</div>
        </div> -->
      </div>
    </div>

    <!-- 邀请 -->
    <el-drawer
        custom-class="custom-drawer"
        v-model="inviteDrawer"
        title="邀请成员"
        direction="rtl"
    >
      <el-form label-position="top" :model="inviteForm" style="max-width: 460px">
        <el-form-item label="通过房间号邀请">
          <el-input v-model="inviteForm.roomId" readonly>
            <template #suffix>
              <div
                  class="i-mdi-content-copy active:scale-125"
                  @click="copyHandler(inviteForm.roomId)"
              ></div>
            </template>
          </el-input>
        </el-form-item>
        <el-form-item label="通过房间链接邀请">
          <el-input v-model="inviteForm.webLink" readonly>
            <template #suffix>
              <div
                  class="i-mdi-content-copy active:scale-125"
                  @click="copyHandler(inviteForm.webLink)"
              ></div>
            </template>
          </el-input>
        </el-form-item>
      </el-form>
    </el-drawer>
  </div>
</template>

<script lang="ts" setup>
import type {Client, LocalStream, RemoteStream} from "trtc-js-sdk";
import TRTC from "trtc-js-sdk";
import {onMounted, reactive, ref, nextTick, watch} from "vue";
import {useRoute, useRouter} from "vue-router";
import {getSign} from "@/utils/sign";
import {copyText} from "vue3-clipboard";
import {ElMessage} from "element-plus/es";
// 设置日志等级
TRTC.Logger.setLogLevel(TRTC.Logger.LogLevel.ERROR);

let localClient: Client;
let localStream: LocalStream;

const router = useRouter();
const route = useRoute();
const appConf = reactive({
  userId: "",
  roomId: 0,
  sdkAppId: 0,
  userSig: "",
});

const getUserId = () => "123";

onMounted(async () => {
  appConf.userId = getUserId();
  appConf.roomId = parseInt(route.query.roomId as string, 10);

  const {sdkAppId, userSig} = await getSign(appConf.userId);
  appConf.sdkAppId = sdkAppId;
  appConf.userSig = userSig;
  handlerJoin();
});

const handlerJoin = async () => {
  const {userId, userSig, roomId, sdkAppId} = appConf;
  console.log({userId, userSig, roomId, sdkAppId});

  try {
    // 创建客户端
    localClient = TRTC.createClient({
      mode: "rtc",
      sdkAppId,
      userId,
      userSig,
    });
    //
    await localClient.join({roomId});
  } catch (e: any) {
    console.log("加入房间失败", e);
  }
  installEventHandlers();
  await createStream();
  await publishHandler();
};

const nothingHandle = () => {
};
const handleStreamAdded = (event: any) => {
  const remoteStream = event.stream;
  const id = remoteStream.getId();
  const userId = remoteStream.getUserId();
  if (remoteStream.getUserId() === `share_${userId}`) {
    localClient.unsubscribe(remoteStream).catch((error: any) => {
    });
  } else {
    localClient.subscribe(remoteStream).catch((error: any) => {
    });
  }
};
// 列表
const remoteStreamsList = ref<Array<RemoteStream>>([]);
const handleStreamSubscribed = async (event: any) => {
  const remoteStream = event.stream;
  const id = remoteStream.getId();
  const userId = remoteStream.getUserId();
  remoteStreamsList.value = [...remoteStreamsList.value, remoteStream];
  // 播放
  console.log("userId", userId, id);
  await nextTick();
  await remoteStream.play(id);
};
const handleStreamRemoved = (event: any) => {
  const remoteStream = event.stream;
  const id = remoteStream.getId();
  remoteStreamsList.value = remoteStreamsList.value.filter(
      (stream) => stream.getId() !== id
  );
};
const installEventHandlers = () => {
  if (!localClient) return;
  localClient.on("error", nothingHandle);
  localClient.on("client-banned", nothingHandle);
  localClient.on("peer-join", nothingHandle);
  localClient.on("peer-leave", nothingHandle);
  localClient.on("stream-added", handleStreamAdded);
  localClient.on("stream-subscribed", handleStreamSubscribed);
  localClient.on("stream-removed", handleStreamRemoved);
  localClient.on("stream-updated", nothingHandle);
  localClient.on("mute-video", nothingHandle);
  localClient.on("mute-audio", nothingHandle);
  localClient.on("unmute-video", nothingHandle);
  localClient.on("unmute-audio", nothingHandle);
};
const uninstallEventHandlers = () => {
  if (!localClient) return;
  localClient.on("error", nothingHandle);
  localClient.on("client-banned", nothingHandle);
  localClient.on("peer-join", nothingHandle);
  localClient.on("peer-leave", nothingHandle);
  localClient.on("stream-added", handleStreamAdded);
  localClient.on("stream-subscribed", handleStreamSubscribed);
  localClient.on("stream-removed", handleStreamRemoved);
  localClient.on("stream-updated", nothingHandle);
  localClient.on("mute-video", nothingHandle);
  localClient.on("mute-audio", nothingHandle);
  localClient.on("unmute-video", nothingHandle);
  localClient.on("unmute-audio", nothingHandle);
};

/**
 * 流处理
 */
const createStream = async () => {
  try {
    if (streamMode.value === "screenStream") localStream = await creatScreenStream();
    if (streamMode.value === "cameraStream") localStream = await createCameraStream();
    // 主屏幕显示流
    await localStream.play("stream_main");
  } catch (e: any) {
    throw new Error(e);
  }
};
// 摄像头流
const createCameraStream = async () => {
  const {userId, userSig, roomId, sdkAppId} = appConf;
  let localStream;
  try {
    // const cameraItems = await TRTC.getCameras();
    // const microphoneItems = await TRTC.getMicrophones();
    // console.log(cameraItems, "cameraItems");

    localStream = TRTC.createStream({
      userId: userId,
      audio: true,
      video: true,
      // cameraId: cameraItems[0].deviceId,
      // microphoneId: microphoneItems[0].deviceId,
    });
    await localStream.initialize();
  } catch (e: any) {
    throw new Error(e);
  }
  return localStream;
};
// 屏幕流
const creatScreenStream = async () => {
  const {userId, userSig, roomId, sdkAppId} = appConf;
  let localStream;
  try {
    localStream = TRTC.createStream({
      audio: false,
      screen: true,
      userId,
    });
    await localStream.initialize();
  } catch (e: any) {
    throw new Error(e);
  }
  return localStream;
};
// 推流
const publishHandler = async () => {
  if (!localClient || !localStream) return;
  try {
    await localClient.publish(localStream);
    console.log("推流成功");
  } catch (e: any) {
    console.log("推流失败", e);
  }
};
// 取消推流
const unpublishHandler = async () => {
  if (!localClient || !localStream) return;
  try {
    await localClient.unpublish(localStream);
  } catch (e: any) {
    throw new Error(e);
  }
};

// 麦克风
const microStatus = ref(true);
const microphoneHandler = () => {
  if (microStatus.value) {
    localStream.muteAudio();
  } else {
    localStream.unmuteAudio();
  }
  microStatus.value = !microStatus.value;
};
// 视频
const cameraStatus = ref(true);
const cameraHandler = async () => {
  // 停止videoTrack并释放摄像头资源
  if (cameraStatus.value) {
    const videoTrack = localStream.getVideoTrack();
    if (videoTrack) {
      await localStream.removeTrack(videoTrack);
      videoTrack.stop();
    }
  } else {
    const stream = await createCameraStream();
    const videoTrack = stream.getVideoTrack();
    await localStream.addTrack(videoTrack as MediaStreamTrack);
  }
  cameraStatus.value = !cameraStatus.value;
};

const streamMode = ref("cameraStream");
// 共享屏幕
const shareScreenStatus = ref(false);
const shareScreenHandler = async () => {
  const resetStream = async () => {
    await unpublishHandler();
    if (localStream) {
      localStream.stop();
      localStream.close();
      localStream = null as any;
    }
  };
  const resetCamera = async () => {
    streamMode.value = "cameraStream";
    shareScreenStatus.value = false;
    await createStream();
    await publishHandler();
  };
  try {
    await resetStream();
    let mode = "cameraStream";
    if (!shareScreenStatus.value) mode = "screenStream";
    streamMode.value = mode;
    await createStream();
    await publishHandler();

    // 点击浏览器自带关闭共享
    if (streamMode.value === "screenStream")
      localStream.on("screen-sharing-stopped", async () => {
        await resetStream();
        await resetCamera();
      });

    shareScreenStatus.value = !shareScreenStatus.value;
  } catch (e: any) {
    await resetStream();
    await resetCamera();
    throw new Error(e);
  }
};

// 全屏处理
const isFull = ref(false);
const fullScreenHandler = () => {
  if (!isFull.value) {
    handleFull();
  } else {
    handleExitFull();
  }
  isFull.value = !isFull.value;
};
const handleFull = () => {
  let element: any;
  element = document.documentElement;
  if (element.requestFullscreen) {
    element.requestFullscreen();
  } else if (element.webkitRequestFullScreen) {
    element.webkitRequestFullScreen();
  } else if (element.mozRequestFullScreen) {
    element.mozRequestFullScreen();
  } else if (element.msRequestFullscreen) {
    element.msRequestFullscreen();
  } else {
    alert("当前浏览器不支持全屏显示！");
  }
};
// 退出全屏
const handleExitFull = () => {
  const doc = document as any;
  if (doc.exitFullscreen) {
    doc.exitFullscreen();
  } else if (doc.webkitCancelFullScreen) {
    doc.webkitCancelFullScreen();
  } else if (doc.mozCancelFullScreen) {
    doc.mozCancelFullScreen();
  } else if (doc.msExitFullscreen) {
    doc.msExitFullscreen();
  }
};

// 邀请
const inviteDrawer = ref(false);
const inviteForm = reactive({
  roomId: "",
  webLink: "",
});
const inviteShow = () => {
  const {userId, userSig, roomId, sdkAppId} = appConf;
  const {origin, pathname} = window.location;
  inviteDrawer.value = true;
  inviteForm.roomId = `${roomId}`;
  inviteForm.webLink = `${origin}?roomId=${roomId}`;
};

// 结束群聊
const handleLeave = async () => {
  await unpublishHandler();
  try {
    uninstallEventHandlers();
    if (localClient) await localClient.leave();
    if (localStream) {
      localStream.stop();
      localStream.close();
      localStream = null as any;
    }
    router.push({path: "/"});
  } catch (e: any) {
    console.log(e, "报错");
  }
};

const copyHandler = async (text: string) => {
  copyText(text, undefined, (error: any) => {
    if (error) {
      ElMessage({message: "复制失败", type: "error"});
    } else {
      ElMessage({message: "复制成功!", type: "success"});
    }
  });
};
</script>

<style lang="scss" scoped>
.page-container {
  @apply w-screen h-screen relative flex justify-around align-center items-center;

  &:hover {
    .top-bar,
    .bottom-bar,
    .stream-list {
      @apply opacity-100;
    }
  }

  .action-p {
    font-style: normal;
    font-weight: 400;
    font-size: 18px;
    line-height: 34px;
    color: rgba(255, 255, 255, 0.68);
  }

  .top-bar,
  .bottom-bar,
  .stream-list {
    @apply transition duration-500;
    @apply opacity-0 absolute bg-gray-800 w-screen z-10;
  }

  .top-bar {
    @apply top-0 h-10 p-x-10;
  }

  .bottom-bar {
    @apply bottom-0 h-20 flex justify-between p-x-10;
    .left,
    .center,
    .right {
      @apply flex items-center;
    }

    .icon-item + .icon-item {
      @apply ml-4;
    }

    .icon-item {
      @apply w-14 h-full flex flex-col justify-center items-center;
      &:hover {
        @apply border-b-blue border-b-2 cursor-pointer;
      }

      .icon {
        @apply text-white text-3xl;
      }

      .text {
        @apply text-white text-xs mt-2;
      }
    }

    .button {
      text-align: center;
      line-height: 56px;
      color: #FFFFFF;
    }
  }

  .page-content {
    @apply flex w-screen h-screen;
    .stream-main {
      @apply w-full h-full bg-gray-700;
    }

    .stream-list {
      @apply w-60 right-0 top-10 bottom-20 overflow-y-scroll bg-gray-900 p-2;
      &::-webkit-scrollbar {
        width: 4px;
      }

      &::-webkit-scrollbar:hover {
        width: 7px;
      }

      .stream-item + .stream-item {
        @apply mt-4;
      }

      .stream-item {
        @apply h-30 bg-gray-700;
      }
    }
  }
}
</style>
<style lang="scss">
.custom-drawer {
  @apply bg-gray-800;
}
</style>
